unit uADODatabase;

interface

uses
  SysUtils, Classes, ActiveX, Variants, Windows, DB, ADODB,
  uDZSysUtils, uDZPersistent, uDZSerializer, uDZLinkList, uDzStream,
  uDZDataSetSerializer, uDZConfig, uDZThread, uDZTrace, uDZStr,
  uGxtSvcIntf, uCxtConst, uCxtTypes, uCxtPackage,uAppConfig, uAppLog,
  uCLDWProtocol, uLBMPTrackClient, uCxtUser, uCxtDAL, uDBConnPool;

type
  TADODatabase = class(TDzInterfacedObject,
                            IAccountDatabase,
                            IVehicleDatabase,
                            ILbmpTrackDatabase)
  protected
    function GetSingleField(const Command: WideString; const Name: string;
      var Value: Variant; var Error: TErrorInfo): Boolean;
    function GetRow(const Command: WideString; Model: TDzPersistent;
      var Error: TErrorInfo): Boolean;
    function ExecCommand(const Command: WideString; var Error: TErrorInfo;
      Affected: PInteger = nil): Boolean;
    function CheckCache(const Table, Filter: string; Model: TDzPersistent): Boolean;
    function GetPagedRecords(Access: TADOAccess; PageNo, PageSize: Integer;
      const IndexField, SelFields, From, Condition, OrderBy: WideString;
      out Total: Integer; var Error: TErrorInfo): Boolean;
    function UpdateLocTrace(Tracing: TVehicleTracing;
      var Error: TErrorInfo): Boolean;
    function AddOrModifyPriVehicle(Operation: TOperation;
      Vehicle: TVehicle; var Error: TErrorInfo): Boolean;
  public
    constructor Create;
    destructor Destroy; override;

    //IAccountDatabase
    function GetAgencyInfo(CityID: Integer; Agency: TAgency;
      var Error: TErrorInfo): Boolean;
    function AddAccount(UserInfo: TUserInfo; var Error: TErrorInfo): Boolean;
    function ModifyAccount(UserInfo: TUserInfo; var Error: TErrorInfo): Boolean;
    function ModifyPassword(UserID: Integer; const OldPassword, NewPassword: AnsiString;
      var Error: TErrorInfo): Boolean;
    function LockUserByID(UserID: Integer; const ComputerID: AnsiString;
      const Reason: WideString; var Error: TErrorInfo): Boolean;
    function GetUserInfo(const UserName: string; UserInfo: TUserInfo;
      var Error: TErrorInfo): Boolean;
    function GetUserLocatePoint(UserId: Integer; var Quantity: Integer;
      var Error: TErrorInfo): Boolean;
    function DecUserLocatePoint(UserID, Quantity: Integer;
      var Error: TErrorInfo): Boolean;
    function GetUserSmsPoint(UserId: Integer; var Quantity: Integer;
      var Error: TErrorInfo): Boolean;
    function DecUserSmsPoint(UserId, Quantity: Integer;
      var Error: TErrorInfo): Boolean;
    function SaveLogin(UserID: Integer; LoginTime: TDateTime;
      const Source, ComputerID: AnsiString; var Error: TErrorInfo): Boolean;
    function SaveSms(const Sender, Recver, Content: WideString;
      SendTime: TDateTime; var Error: TErrorInfo): Boolean;
    function ModifyComputerID(UserID: Integer; const ComputerID: AnsiString;
      var Error: TErrorInfo): Boolean;
    function LockComputer(const ComputerID: AnsiString;
      const Reason: WideString; var Error: TErrorInfo): Boolean;
    function UnlockCompter(const ComputerID: AnsiString;
      var Error: TErrorInfo): Boolean;
    function IsComputerLocked(const ComputerID: AnsiString;
      var Reason: WideString; var Error: TErrorInfo): Boolean;

    //IVehicleDatabase
    function GetPriVehicle(UserId, PageSize, PageNo: Integer;
      Filter: TPriVehicleFilter; List: TDzPersistentList;
      out Total: Integer; var Error: TErrorInfo): Boolean;
    function GetShareVehicle(ObjectType: TLBSObjectType;
      Filter: TShareVehicleFilter; PageNo, PageSize: Integer;
      List: TDzPersistentList; out Total: Integer;
      var Error: TErrorInfo): Boolean;
    function RemovePriVehicle(List: TDzPersistentList;
      var Removed: Integer; var Error: TErrorInfo): Boolean;
    function AddPriVehicle(Vehicle: TVehicle;
      var Error: TErrorInfo): Boolean;
    function ModifyPriVehicle(Vehicle: TVehicle;
      var Error: TErrorInfo): Boolean;
    function RemoveLocPerson(List: TDzPersistentList;
      var Removed: Integer; var Error: TErrorInfo): Boolean;
    function AddLocPerson(List: TDzPersistentList;
      out Added: Integer; var Error: TErrorInfo): Boolean;
    function ModifyLocPerson(List: TDzPersistentList;
      out Modified: Integer; var Error: TErrorInfo): Boolean;
    function GetLocPerson(UserID, PageNo, PageSize: Integer;
      Filter: TLocPersonFilter; List: TDzPersistentList;
      out Total: Integer; var Error: TErrorInfo): Boolean;
    function SaveLocateResult(const Phone, Longitude, Latitude: AnsiString;
      Address, CityName: WideString; CityID, UserID, ObjectID, Consume: Integer;
      Method: TLbmpLocType; var Error: TErrorInfo): Boolean;
    function SetAutoLocTime(UserID, Hour: Integer; var Error: TErrorInfo): Boolean;
    function GetLocTrace(ID: Integer; Tracing: TVehicleTracing;
      var Error: TErrorInfo): Boolean;
    function AddLocTrace(Tracing: TVehicleTracing;
      var Error: TErrorInfo): Boolean;
    function RemoveLocTrace(ID: Integer; var Error: TErrorInfo): Boolean;
    function ModifyLocTrace(Tracing: TVehicleTracing;
      var Error: TErrorInfo): Boolean;
    function ModifyLBMPState(const Phone: AnsiString; State: Integer;
      var Error: TErrorInfo): Boolean;

    //ILBMPTrackDatabase
    function GetTrack(const Phone: string; list: TDzPersistentList): Integer;
    procedure AddToTrack(const Phone: AnsiString; LocType: TLbmpLocType;
      LocTime: TDateTime; CityID: Integer; const Longitude,
      Latitude: AnsiString; const Address: WideString);
    function ILBMPTrackDatabase.Get = GetTrack;
    procedure ILBMPTrackDatabase.Add = AddToTrack;
  end;

implementation

procedure WriteFieldNames(dataset: TDataSet);
var
  i: Integer;
begin
  for i := 0 to dataset.FieldCount - 1 do
    WriteLog(tsDebug, dataset.Fields[i].FieldName);
end;

function SystemBusy(var Error: TErrorInfo): Boolean; inline;
begin
  Error.Code := CXT_E_SYSTEM_BUSY;
  Error.Desc := SSystemBusy;
  Result := False;
end;

function CodecError(var Error: TErrorInfo): Boolean; inline;
begin
  Error.Code := CXT_E_SERIALIZING;
  Error.Desc := SCodecError;
  Result := False;
end;

{ TADODatabase }

function TADODatabase.AddAccount(UserInfo: TUserInfo;
  var Error: TErrorInfo): Boolean;
var
  access: TADOAccess;
begin
  access := GetDBConnPool.GetConnection;
  if access = nil then
  begin
    Result := SystemBusy(Error);
    Exit;
  end;
  with access, access.StoredProc, access.StoredProc.Parameters do
  try
    ProcedureName := '[Cxt_56888_net].[dbo].[Users_AddUsers_Front]';
    Clear;
    CreateParameter('Use_UserName',ftString, pdInput, 200, UserInfo.UserName);
    CreateParameter('Use_Type', ftInteger, pdInput, 4, UserInfo.UserType);
    CreateParameter('Use_PetName', ftString, pdInput, 20, null);
    CreateParameter('Use_RealName', ftString, pdInput, 20, UserInfo.RealName);
    CreateParameter('Use_Sex', ftInteger, pdInput, 4, UserInfo.Sex);
    CreateParameter('Use_IDCardNo', ftString, pdInput, 18, UserInfo.IDCardNo);
    CreateParameter('Use_Password', ftString, pdInput, 50, UserInfo.Password);
    CreateParameter('Use_Email', ftString, pdInput, 50, null);
    CreateParameter('Use_CityCode', ftInteger, pdInput, 4, UserInfo.CityCode);
    CreateParameter('Use_Tel', ftString, pdInput, 20, UserInfo.Telephone);
    CreateParameter('Use_TelExt', ftString, pdInput, 20, null);
    CreateParameter('Use_NetTel', ftString, pdInput, 20, null);
    CreateParameter('Use_Add', ftString, pdInput, 500, UserInfo.Address);
    CreateParameter('Use_Corp', ftString, pdInput, 500, UserInfo.CompanyName);
    CreateParameter('Use_DiskKeyNo', ftString, pdInput, 20, null);
    CreateParameter('Use_Img', ftString, pdInput, 20, '');
    CreateParameter('Use_MobileNo', ftString, pdInput, 20, UserInfo.MobilePhone);
    CreateParameter('Use_Url', ftString, pdInput, 100, UserInfo.Website);
    CreateParameter('ReturnCode', ftInteger, pdOutput, 4, null);
    Result := ExecStoredProc(Error, True);
    if Result then
    begin
      UserInfo.UserID := ParamValues['ReturnCode'];
      if UserInfo.UserID = -1 then
      begin
        Error.Code := CXT_E_PRIMARYKEY_COLLISION;
        Error.Desc := SUserNameExists;
      end;
    end
  finally
    GetDBConnPool.ReleaseConnection(access);
  end;
end;

function TADODatabase.AddLocPerson(List: TDzPersistentList;
  out Added: Integer; var Error: TErrorInfo): Boolean;
var
  access: TADOAccess;
  i: Integer;
  person: TLocPerson;
begin
  access := GetDBConnPool.GetConnection;
  if access = nil then
  begin
    Result := SystemBusy(Error);
    Exit;
  end;
  Added := 0;
  Result := False;
  with access, access.StoredProc, access.StoredProc.Parameters do
  try
    ProcedureName := '[Cxt_56888_net].[dbo].[CarInfo_AddPeopleInfo]';
    Clear;
    CreateParameter('SuiCheShouJi',ftString, pdInput, 50, null);
    CreateParameter('SiJiXingMing', ftString, pdInput, 50, null);
    CreateParameter('Sex', ftString, pdInput, 2, null);
    CreateParameter('ZhuCeFou', ftInteger, pdInput, 4, -1);
    CreateParameter('InfoType', ftInteger, pdInput, 4, 2);
    CreateParameter('BeiZhu', ftString, pdInput, 1000, null);
    CreateParameter('SuoShuYongHu', ftInteger, pdInput, 4, null);
    CreateParameter('ReturnCode', ftInteger, pdOutput, 4, null);
    for i := 0 to List.Count - 1 do
    begin
      person := TLocPerson(List[i]);
      Items[0].Value := person.Phone;
      Items[1].Value := person.Name;
      Items[2].Value := person.Sex;
      Items[3].Value := -1;
      Items[5].Value := person.Remark;
      Items[6].Value := person.UserID;
      Result := ExecStoredProc(Error, True);
      if Result then Inc(Added)
      else Break;
    end;
  finally
    GetDBConnPool.ReleaseConnection(access);
  end;
  if (Added <> 0) and not Result then
  begin
    Error.Code := CXT_E_SUCCESS;
    Result := True;
  end;
end;

function TADODatabase.AddLocTrace(tracing: TVehicleTracing;
  var Error: TErrorInfo): Boolean;
begin
  Result := UpdateLocTrace(tracing, Error);
end;

function TADODatabase.AddOrModifyPriVehicle(Operation: TOperation;
  Vehicle: TVehicle; var Error: TErrorInfo): Boolean;
var
  access: TADOAccess;
begin
  vehicle.StateCode := -1;
  access := GetDBConnPool.GetConnection;
  if access = nil then
  begin
    Result := SystemBusy(Error);
    Exit;
  end;
  try
    case Operation of
      opAdd: access.StoredProc.ProcedureName :=
        '[Cxt_56888_net].[dbo].[CarInfo_AddCarInfo]';
      opModify: access.StoredProc.ProcedureName :=
        '[Cxt_56888_net].[dbo].[CarInfo_UpdateCarInfo]';
    end;
    with access.StoredProc.Parameters, Vehicle do
    begin
      Clear;
      CreateParameter('CheLiangBianHao', ftInteger, pdInput, 4, GUID);
      CreateParameter('SuiCheShouJi', ftString, pdInput, 50, Phone);
      CreateParameter('SiJiXingMing', ftString, pdInput, 50, SiJiXingMing);
      CreateParameter('ChePaiHaoMa', ftString, pdInput, 50, Name);
      CreateParameter('QiWangLiuXiang', ftString, pdInput, 50, QiWangLiuXiang);
      CreateParameter('HuoYunZhuangTai', ftString, pdInput, 20, HuoYunZhuangTai);
      CreateParameter('ToCityCode', ftString, pdInput, 256, ToCityCode);
      CreateParameter('CheXing', ftString, pdInput, 100, CheXing);
      CreateParameter('CheXing_A', ftString, pdInput, 100, '');
      CreateParameter('CheXing_B', ftString, pdInput, 100, '');
      CreateParameter('CheXing_C', ftString, pdInput, 100, '');
      CreateParameter('CheXing_D', ftString, pdInput, 100, '');
      CreateParameter('CheZhang', ftString, pdInput, 50, CheZhang);
      CreateParameter('CheGao', ftString, pdInput, 50, CheGao);
      CreateParameter('CheKuan', ftString, pdInput, 50, CheKuan);
      CreateParameter('DunWei', ftString, pdInput, 100, DunWei);
      CreateParameter('RongJi', ftString, pdInput, 50, RongJi);
      CreateParameter('ZhuCeFou', ftInteger, pdInput, 4, StateCode);
      CreateParameter('FaDongJiHao', ftString, pdInput, 50, FaDongJiHao);
      CreateParameter('CheJiaHaoMa', ftString, pdInput, 50, Name);
      CreateParameter('BaoXianKaHao', ftString, pdInput, 50, BaoXianKaHao);
      CreateParameter('GuaKaoDanWei', ftString, pdInput, 50, GuaKaoDanWei);
      CreateParameter('YunYingZhengShu', ftString, pdInput, 50, YunYingZhengShu);
      CreateParameter('CheZhuXingMing', ftString, pdInput, 50, CheZhuXingMing);
      CreateParameter('CheZhuXingBie', ftString, pdInput, 50, CheZhuXingBie);
      CreateParameter('CheZhuShenFenZhengHao', ftString, pdInput, 50, CheZhuShenFenZhengHao);
      CreateParameter('CheZhuDianHuaHaoMa', ftString, pdInput, 50, CheZhuDianHuaHaoMa);
      CreateParameter('CheZhuQiTaDianHua', ftString, pdInput, 50, CheZhuQiTaDianHua);
      CreateParameter('CheZhuShouJi', ftString, pdInput, 50, CheZhuShouJi);
      CreateParameter('CheZhuJiaTingZhuZhi', ftString, pdInput, 50, CheZhuJiaTingZhuZhi);
      CreateParameter('SiJiXingBie', ftString, pdInput, 50, SiJiXingBie);
      CreateParameter('SiJiShenFenZhengHao', ftString, pdInput, 50, SiJiShenFenZhengHao);
      CreateParameter('JiaShiZhiZhao', ftString, pdInput, 50, JiaShiZhiZhao);
      CreateParameter('SiJiJiaTingDianHua', ftString, pdInput, 50, SiJiJiaTingDianHua);
      CreateParameter('SiJiQiTaDianHua', ftString, pdInput, 50, SiJiQiTaDianHua);
      CreateParameter('SiJiJiaTingZhuZhi', ftString, pdInput, 100, SiJiJiaTingZhuZhi);
      CreateParameter('BeiZhu', ftString, pdInput, 1000, BeiZhu);
      CreateParameter('SuoShuYongHu', ftInteger, pdInput, 50, SuoShuYongHu);
      CreateParameter('InfoType', ftInteger, pdInput, 4, 1);
      CreateParameter('ReturnCode', ftInteger, pdOutput, 4, 0);
      Result := access.ExecStoredProc(Error, True);
      if Result then vehicle.GUID := ParamValues['ReturnCode'];
    end;
  finally
    GetDBConnPool.ReleaseConnection(access);
  end;
end;

function TADODatabase.AddPriVehicle(vehicle: TVehicle;
  var Error: TErrorInfo): Boolean;
begin
  Result := AddOrModifyPriVehicle(opAdd, vehicle, Error);
end;

procedure TADODatabase.AddToTrack(const Phone: AnsiString;
  LocType: TLbmpLocType; LocTime: TDateTime; CityID: Integer;
  const Longitude, Latitude: AnsiString; const Address: WideString);
begin

end;

function TADODatabase.CheckCache(const Table, Filter: string;
  Model: TDzPersistent): Boolean;
begin
  Result := False;
end;

constructor TADODatabase.Create;
begin
  CoInitialize(nil);
end;

destructor TADODatabase.Destroy;
begin
  CoUninitialize;
  inherited;
end;

function TADODatabase.ExecCommand(const Command: WideString;
  var Error: TErrorInfo; Affected: PInteger): Boolean;
var
  access: TADOAccess;
  num: Integer;
begin
  access := GetDBConnPool.GetConnection;
  if access = nil then
  begin
    Result := SystemBusy(Error);
    Exit;
  end;
  if Affected = nil then Affected := @num;
  try
    Result := access.ExecSQL(Command, Error, True, Affected);
    if Result and (affected^ = 0) and (affected <> @num) then
    begin
      Error.Code := CXT_E_NO_DATA;
      Result := False;
    end;
  finally
    GetDBConnPool.ReleaseConnection(access);
  end;
end;

function TADODatabase.GetAgencyInfo(CityID: Integer; Agency: TAgency;
  var Error: TErrorInfo): Boolean;
begin
  Result := GetRow(WideFormat('select top 1 [UserEmail] as Telephone, ' +
    '[UserName] as RealName from [Cxt_56888_net].[dbo].[Rights_Users] ' +
    'where UserAgentCity like ''%%%d%%'' order by len(UserID)', [CityID]),
    Agency, Error);
end;

function TADODatabase.GetLocPerson(userID, pageNo, pageSize: Integer;
  filter: TLocPersonFilter; list: TDzPersistentList;
  out total: Integer; var Error: TErrorInfo): Boolean;
var
  access: TADOAccess;
  orderBy: WideString;
  conds: TDzWideStrStream;
  procedure AddCondition(const s: WideString);
  begin
    if conds.Position > 0 then conds.WriteString(' and ');
    conds.WriteString(s);
  end;
  function MapFiledName(const s: string): string;
  begin
    if (SameText(s, 'Phone')) then Result := 'SuiCheShouJi'
    else if (SameText(s, 'Name')) then Result := 'SiJiXingMing'
    else if (SameText(s, 'LastLocateTime')) then Result := 'DingWeiShiJian'
    else if (SameText(s, 'Position')) then Result := 'CheLiangWeiZhi'
    else if (SameText(s, 'Address')) then Result := 'WeiZhiMiaoShu'
    else if (SameText(s, 'LSSText')) then Result := 'ZhuCeFou'
    else Result := s;
  end;
begin
  access := GetDBConnPool.GetConnection;
  if access = nil then
  begin
    Result := SystemBusy(Error);
    Exit;
  end;
  conds := TDzWideStrStream.Create('');
  conds.Size := 512;
  conds.WriteString(WideFormat(
    'A.Car_Del = 0 AND A.SuoShuYongHu = %d AND A.Car_InfoType = 2', [userId]));
  try
    if filter.Enabled then
    begin
      if filter.PersonName <> '' then
        AddCondition(WideFormat('A.SiJiXingMing like ''%%%s%%''',
          [filter.PersonName]));
      if filter.Phone <> '' then
        AddCondition(WideFormat('A.SuiCheShouJi like ''%%%s%%''',
          [filter.Phone]));
      if filter.Sex <> '' then
        AddCondition(WideFormat('A.SiJiXingBie = ''%s''', [filter.Sex]));
      if filter.CityCodes <> '' then
        AddCondition(WideFormat('A.CityCode in (%s)', [filter.CityCodes]));
    end;
    if filter.SortFields = '' then orderBy := ''
    else begin
      case filter.SortDirection of
        sdNone: orderBy := '';
        sdAscendent: orderBy := MapFiledName(filter.SortFields) + ' asc';
        sdDescendent: orderBy := MapFiledName(filter.SortFields) + ' desc';
      end;
    end;
    if orderBy = '' then orderBy := 'CheLiangBianHao'
    else orderBy := orderBy + ', CheLiangBianHao';
    conds.Size := conds.Position;
    Result := GetPagedRecords(access, pageNo + 1, pageSize,
      'CheLiangBianHao',
      'CheLiangBianHao as [GUID], SuiCheShouJi as [Phone], ' +
      'SiJiXingMing as [Name], SiJiXingBie as Sex, CityCode as CityID, ' +
      'DingWeiShiJian as LastLocateTime, ZhuCeFou as StateCode, ' +
      'CheLiangWeiZhi as [Position], WeiZhiMiaoShu as [Address], ' +
      'JingDu as Longitude, WeiDu as Latitude, BeiZhu as Remark',
      '[Cxt_56888_net].[dbo].CarInfo A',
      conds.DataString, orderBy, total, Error);
    if Result then
    begin
      try
        list.LoadFromDataSet(access.StoredProc);
      except
        Error.Code := CXT_E_SERIALIZING;
        Error.Desc := SCodecError;
        Result := False;
      end;
    end;
  finally
    conds.Free;
    GetDBConnPool.ReleaseConnection(access);
  end;
end;

function TADODatabase.GetTrack(const Phone: string;
  list: TDzPersistentList): Integer;
var
  access: TADOAccess;
  error: TErrorInfo;
begin
  access := GetDBConnPool.GetConnection;
  if access = nil then
  begin
    Result := CXT_E_SYSTEM_BUSY;
    Exit;
  end;
  Result := CXT_E_DBENGINE;
  try
    if access.ExecSQL(WideFormat('select top 100 CheLiangWeiZhi as [Position], ' +
      'JingDu as Longitude, WeiDu as Latitude, LocType - 1 as [Method], ' +
      'AddTime as LocateTime, WeiZhiMiaoShu as Address ' +
      'from [Cxt_56888_net].[dbo].[CheLiangGuiJi] ' +
      'where ShouJiHaoMa = %s order by [ID] desc', [Phone]), error) then
    begin
      try
        list.LoadFromDataSet(access.Query);
        Result := CXT_E_SUCCESS;
      except
        Result := CXT_E_SERIALIZING;
      end;
    end;
  finally
    GetDBConnPool.ReleaseConnection(access);
  end;
end;

function TADODatabase.GetLocTrace(ID: Integer;
  Tracing: TVehicleTracing; var Error: TErrorInfo): Boolean;
var
  access: TADOAccess;
begin
  access := GetDBConnPool.GetConnection;
  if access = nil then
  begin
    Result := SystemBusy(Error);
    Exit;
  end;
  try
    Tracing.CarID := ID;
    Result := access.ExecSQL(WideFormat('SELECT A.*, B.ChePaiHaoMa AS ' +
      'PlateNumber FROM [Cxt_56888_net].[dbo].CarInfo_AutoLoc A INNER JOIN ' +
      '[Cxt_56888_net].[dbo].CarInfo B ON A.CarID = B.CheLiangBianHao ' +
      'where A.CarID = %d', [ID]), Error);
    if not Result then Exit;
    if access.Query.IsEmpty then
    begin
      Error.Code := CXT_E_NO_DATA;
      Result := False;
    end
    else try
      Tracing.Load(access.ClassReader);
    except
      Error.Code := CXT_E_SERIALIZING;
      Error.Desc := SCodecError;
      Result := False;
    end;
  finally
    GetDBConnPool.ReleaseConnection(access);
  end;
end;

function TADODatabase.GetPagedRecords(Access: TADOAccess; PageNo, PageSize: Integer;
  const IndexField, SelFields, From, Condition, OrderBy: WideString;
  out Total: Integer; var Error: TErrorInfo): Boolean;
begin
  with access.StoredProc, access.StoredProc.Parameters do
  begin
    Clear;
    ProcedureName := '[Cxt_56888_net].[dbo].[GetPagedRecord]';
    CreateParameter('pageIndex', ftInteger, pdInput, 4, PageNo);
    CreateParameter('pageSize', ftInteger, pdInput, 4, PageSize);
    CreateParameter('indexField', ftWideString, pdInput, 256, IndexField);
    CreateParameter('selFields', ftWideString, pdInput, 1024, SelFields);
    CreateParameter('fromObjects', ftWideString, pdInput, 1024, From);
    CreateParameter('condition', ftWideString, pdInput, 2048, Condition);
    CreateParameter('orderBy', ftWideString, pdInput, 1024, OrderBy);
    CreateParameter('totalRecords', ftInteger, pdOutput, 4, Total);
    Result := access.ExecStoredProc(Error, False);
    if Result then Total := ParamValues['totalRecords'];
  end;
end;

function TADODatabase.GetPriVehicle(UserID, PageSize, PageNo: Integer;
  Filter: TPriVehicleFilter; List: TDzPersistentList;
  out Total: Integer; var Error: TErrorInfo): Boolean;
var
  access: TADOAccess;
  conds: TDzWideStrStream;
  orderBy: WideString;
  procedure AddCondition(const s: WideString);
  begin
    if conds.Position > 0 then conds.WriteString(' and ');
    conds.WriteString(s); 
  end;
  function MapFiledName(const s: string): string;
  begin
    if SameText(s, 'Phone') then Result := 'SuiCheShouJi'
    else if SameText(s, 'Name') then Result := 'ChePaiHaoMa'
    else if SameText(s, 'LastLocateTime') then Result := 'DingWeiShiJian'
    else if SameText(s, 'Position') then Result := 'CheLiangWeiZhi'
    else if SameText(s, 'Address') then Result := 'WeiZhiMiaoShu'
    else if SameText(s, 'LSSText') then Result := 'ZhuCeFou'
    else if SameText(s, 'StateCode') then Result := 'ZhuCeFou'
    else Result := s;
  end;
begin
  access := GetDBConnPool.GetConnection;
  if access = nil then
  begin
    Result := SystemBusy(Error);
    Exit;
  end;
  conds := TDzWideStrStream.Create('');
  conds.Size := 1024;
  conds.WriteString(WideFormat(
    '(A.Car_Del = 0) and (A.SuoShuYongHu = %d) and ((A.Car_InfoType = 1) or ' +
    '(Car_InfoType = 3))', [userId]));
  try
    if filter.Enabled then
    begin
      case filter.Locatable of
        nbFalse: AddCondition('(A.ZhuCeFou <> 3)');
        nbTrue: AddCondition('(A.ZhuCeFou = 3)');
      end;
      if filter.SiJiXingMing <> '' then
        AddCondition(WideFormat('(A.SiJiXingMing like ''%%%s%%'')',
          [filter.SiJiXingMing]));
      if filter.ChePaiHaoMa <> '' then
        AddCondition(WideFormat('(A.ChePaiHaoMa like ''%%%s%%'')',
          [filter.ChePaiHaoMa]));
      if filter.Phone <> '' then
        AddCondition(WideFormat('(A.SuiCheShouJi like ''%%%s%%'')',
          [filter.Phone]));
      if filter.CheZhang <> '' then
        AddCondition(WideFormat('(A.CheZhang like ''%%%s%%'')', [filter.CheZhang]));
      if filter.BeiZhu <> '' then
        AddCondition(WideFormat('(A.BeiZhu like ''%%%s%%'')', [filter.BeiZhu]));
      if filter.CheGao <> '' then
        AddCondition(WideFormat('(A.CheGao like ''%%%s%%'')', [filter.CheGao]));
      if filter.TuoGuaLunZhou <> '' then
        AddCondition(WideFormat('(A.CheXing_A like ''%%%s%%'')',
          [filter.TuoGuaLunZhou]));
      if filter.HuoXiangJieGou <> '' then
        AddCondition(WideFormat('(A.CheXing_B like ''%%%s%%'')',
          [filter.HuoXiangJieGou]));
      if filter.TeShuGongNeng <> '' then
        AddCondition(WideFormat('(A.CheXing_C like ''%%%s%%'')',
          [filter.TeShuGongNeng]));
      if filter.ChangShangPinPai <> '' then
        AddCondition(WideFormat('(A.CheXing_D like ''%%%s%%'')',
          [filter.ChangShangPinPai]));
      if filter.ToCityCode <> '' then
        AddCondition(WideFormat('exists(select ID from CarInfo_ToCityCode ' +
          'where CheLiangBianHao = A.CheLiangBianHao and ToCityCode in (%s))',
            [filter.ToCityCode]));
      if filter.InCityCode <> '' then
        AddCondition(WideFormat('(A.CityCode in (%s))', [filter.InCityCode]));
    end;
    if filter.SortFields = '' then orderBy := ''
    else begin
      case filter.SortDirection of
        sdNone: orderBy := '';
        sdAscendent: orderBy := MapFiledName(filter.SortFields) + ' asc';
        sdDescendent: orderBy := MapFiledName(filter.SortFields) + ' desc';
      end;
    end;
    if orderBy = '' then orderBy := 'CheLiangBianHao'
    else orderBy := orderBy + ', CheLiangBianHao';
    conds.Size := conds.Position;
    Result := GetPagedRecords(access, pageNo + 1,pageSize,
      'CheLiangBianHao',
      'CheLiangBianHao as [GUID], SuoShuYongHu, SuiCheShouJi as Phone, ' +
      'ChePaiHaoMa as [Name], SiJiXingMing, ' +
      'QiWangLiuXiang, CheXing, HuoYunZhuangTai, CheZhang, CheKuan, CheGao, ' +
      'DunWei, RongJi, BeiZhu, FaDongJiHao, CheJiaHaoMa, BaoXianKaHao, ' +
      'GuaKaoDanWei, YunYingZhengShu, CityCode as CityID, ' +
      'DingWeiShiJian as [LastLocateTime], CheLiangWeiZhi as [Position], ' +
      'CheZhuXingMing, CheZhuShouJi, CheZhuShenFenZhengHao, CheZhuXingBie, ' +
      'CheZhuDianHuaHaoMa, CheZhuQiTaDianHua, CheZhuJiaTingZhuZhi, ' +
      'SiJiShenFenZhengHao, SiJiXingBie, JiaShiZhiZhao, SiJiJiaTingDianHua, ' +
      'SiJiQiTaDianHua, SiJiJiaTingZhuZhi, Car_AddTime, ' +
      'WeiZhiMiaoShu as Address, ZhuCeFou as StateCode, JingDu as Longitude, ' +
      'WeiDu as Latitude',
      '[Cxt_56888_net].[dbo].CarInfo A',
      conds.DataString, orderBy, Total, Error);
    if not Result then
    begin
      Total := 0;
      Exit;
    end;
    try
      List.LoadFromDataSet(access.StoredProc);
    except
      Error.Code := CXT_E_SERIALIZING;
      Error.Desc := SCodecError;
      Result := False;
    end;
  finally
    conds.Free;
    GetDBConnPool.ReleaseConnection(access);
  end;
end;

function TADODatabase.GetRow(const Command: WideString;
  Model: TDzPersistent; var Error: TErrorInfo): Boolean;
var
  access: TADOAccess;
begin
  access := GetDBConnPool.GetConnection;
  if access = nil then
  begin
    Result := SystemBusy(Error);
    Exit;
  end;

  with access do
  try
    Result := ExecSQL(Command, Error);
    if not Result then Exit;
    if Query.IsEmpty then
    begin
      Error.Code := CXT_E_NO_DATA;
      Error.Desc := SUnknownError;
      Result := False;
    end
    else try
      Model.Load(ClassReader);
    except
      Result := CodecError(Error);
    end;
  finally
    GetDBConnPool.ReleaseConnection(access);
  end;
end;

function TADODatabase.GetShareVehicle(ObjectType: TLBSObjectType;
  Filter: TShareVehicleFilter; PageNo, PageSize: Integer;
  List: TDzPersistentList; out Total: Integer; var Error: TErrorInfo): Boolean;
var
  orderBy: WideString;
  conds: TDzWideStrStream;
  typeID: Integer;
  access: TADOAccess;
  fields: WideString;
  procedure AddCondition(const s: WideString);
  begin
    if conds.Position > 0 then conds.WriteString(' and ');
    conds.WriteString(s);
  end;
  function MapFiledName(const s: string): string;
  begin
    if SameText(s, 'Phone') then Result := 'SuiCheShouJi'
    else if SameText(s, 'Name') then Result := 'ChePaiHaoMa'
    else if SameText(s, 'LastLocateTime') then Result := 'DingWeiShiJian'
    else if SameText(s, 'Position') then Result := 'CheLiangWeiZhi'
    else if SameText(s, 'Address') then Result := 'WeiZhiMiaoShu'
    else if SameText(s, 'LSSText') then Result := 'ZhuCeFou'
    else if SameText(s, 'UserName') then Result := 'B.use_UserName'
    else if SameText(s, 'UserCompany') then Result := 'B.use_Corp'
    else if SameText(s, 'UserTelephone') then Result := 'B.use_Tel'
    else if SameText(s, 'UserMobile') then Result := 'B.Use_MobileNo'
    else Result := s;
  end;
begin
  access := GetDBConnPool.GetConnection;
  if access = nil then
  begin
    Result := SystemBusy(Error);
    Exit;
  end;
  if ObjectType = otShare then typeID := 1
  else typeID := 2;
  conds := TDzWideStrStream.Create('');
  conds.Size := 1024;
  conds.WriteString(WideFormat('A.Car_Del = 0 and A.Car_InfoType = 1 ' +
      'and A.Car_Source = %d', [typeID]));
  try
    if filter.Enabled then
    begin
      case filter.Locatable of
        nbTrue: AddCondition('A.ZhuCeFou = 3');
        nbFalse: AddCondition('A.ZhuCeFou <> 3');
      end;
      if filter.CheKuan <> '' then
        AddCondition(WideFormat('A.CheKuan like ''%%%s%%''', [filter.CheKuan]));
      if filter.RongJi <> '' then
        AddCondition(WideFormat('A.RongJi like ''%%%s%%''', [filter.RongJi]));
      if filter.DunWei <> '' then
        AddCondition(WideFormat('A.DunWei = ''%s''', [filter.DunWei]));
      if filter.CheZhang <> '' then
        AddCondition(WideFormat('A.CheZhang = ''%s''', [filter.CheZhang]));
      if filter.BeiZhu <> '' then
        AddCondition(WideFormat('A.BeiZhu like ''%%%s%%''', [filter.BeiZhu]));
      if filter.CheGao <> '' then
        AddCondition(WideFormat('A.CheGao like ''%%%s%%''', [filter.CheGao]));
      if filter.TuoGuaLunZhou <> '' then
        AddCondition(WideFormat('A.CheXing_A like ''%%%s%%''',
          [filter.TuoGuaLunZhou]));
      if filter.HuoXiangJieGou <> '' then
        AddCondition(WideFormat('A.CheXing_B like ''%%%s%%''',
          [filter.HuoXiangJieGou]));
      if filter.TeShuGongNeng <> '' then
        AddCondition(WideFormat('A.CheXing_C like ''%%%s%%''',
          [filter.TeShuGongNeng]));
      if filter.ChangShangPinPai <> '' then
        AddCondition(WideFormat('A.CheXing_D like ''%%%s%%''',
          [filter.ChangShangPinPai]));
      if filter.ToCityCode <> '' then
        AddCondition(WideFormat('exists(select ID from CarInfo_ToCityCode ' +
          'where CheLiangBianHao = A.CheLiangBianHao and ToCityCode in (%s))',
            [filter.ToCityCode]));
      if filter.InCityCode <> '' then
        AddCondition(WideFormat('A.CityCode in (%s)', [filter.InCityCode]));
    end;
    if ObjectType = otShare then
      fields := 'A.CheLiangBianHao as [GUID], ' +
        'A.ChePaiHaoMa as [Name], ' +
        'A.SuiCheShouJi as Phone, A.SiJiXingMing, A.QiWangLiuXiang, ' +
        'A.CheXing, A.CheZhang, A.CheKuan, A.CheGao, A.ZhuCeFou as [StateCode], ' +
        'A.DunWei, case when A.ZhuCeFou = 3 then A.CheLiangWeiZhi else ' +
        'A.CheLiangWeiZhi2 end as [Position], A.WeiZhiMiaoShu as Address, ' +
        'A.Jingdu as Longitude, A.Weidu as Latitude, CityCode as CityID, ' +
        'case when A.ZhuCeFou = 3 then A.DingWeiShiJian ' +
        'else A.Car_AddTime end as LastLocateTime, ' +
        'A.SuoShuYongHu, B.use_UserName as UserName, ' +
        'B.use_Corp as UserCompany, B.Use_Tel as UserTelephone, ' +
        'B.Use_MobileNo as UserMobile, CityCode'
    else
      fields := 'A.CheLiangBianHao as [GUID], A.ChePaiHaoMa as [Name], ' +
        'A.SuiCheShouJi as Phone, A.SiJiXingMing, A.QiWangLiuXiang, ' +
        'A.CheXing, A.CheZhang, A.CheKuan, A.CheGao, A.ZhuCeFou as [StateCode], ' +
        'A.DunWei, case when A.ZhuCeFou = 3 then A.CheLiangWeiZhi else ' +
        'A.CheLiangWeiZhi2 end as [Position], A.WeiZhiMiaoShu as Address, ' +
        'A.Jingdu as Longitude, A.Weidu as Latitude, CityCode as CityID, ' +
        'case when A.ZhuCeFou = 3 then A.DingWeiShiJian ' +
        'else A.Car_AddTime end as LastLocateTime, ' +
        'A.SuoShuYongHu, B.use_UserName as UserName, ' +
        'B.use_Corp as UserCompany, B.Use_Tel as UserTelephone, ' +
        'B.Use_MobileNo as UserMobile, CityCode';
    if filter.SortFields = '' then orderBy := ''
    else begin
      case filter.SortDirection of
        sdNone: orderBy := '';
        sdAscendent: orderBy := MapFiledName(filter.SortFields) + ' asc';
        sdDescendent: orderBy := MapFiledName(filter.SortFields) + ' desc';
      end;
    end;
    if orderBy = '' then orderBy := 'CheLiangBianHao'
    else orderBy := orderBy + ', CheLiangBianHao';
    conds.Size := conds.Position;
    Result := GetPagedRecords(access, pageNo + 1, pageSize,
      'A.CheLiangBianHao', fields,
      '[Cxt_56888_net].[dbo].[CarInfo] A ' +
      'LEFT JOIN [Cxt_56888_net].[dbo].Users B ' +
      'on A.SuoShuYongHu = B.use_ID',
      conds.DataString, orderBy, total, Error);

    if not Result then
    begin
      total := 0;
      Exit;
    end;
    try
      list.LoadFromDataSet(access.StoredProc);
    except
      Result := CodecError(Error);
    end;
  finally
    conds.Free;
    GetDBConnPool.ReleaseConnection(access);
  end;
end;

function TADODatabase.GetSingleField(const Command: WideString; const Name: string;
  var Value: Variant; var Error: TErrorInfo): Boolean;
var
  access: TADOAccess;
begin
  access := GetDBConnPool.GetConnection;
  if not Assigned(access) then
  begin
    Result := SystemBusy(Error);
    Exit;
  end;
  try
    Result := access.ExecSQL(Command, Error);
    if not Result then Exit;
    if access.Query.IsEmpty then
    begin
      error.Code := CXT_E_NO_DATA;
      Result := False;
    end
    else begin
      Value := access.Query.Fields[0].Value;
    end;
  finally
    GetDBConnPool.ReleaseConnection(access);
  end;
end;

function TADODatabase.GetUserInfo(const userName: string;
  UserInfo: TUserInfo; var Error: TErrorInfo): Boolean;
const
  SQLFMT = 'select A.[Use_State] as UserState, A.[Use_ID] as UserID, ' +
    'A.[Use_UserName] as UserName, ' +
    'A.[Use_RealName] as RealName, A.[Use_IDCardNo] as IDCardNo, ' +
    'A.[Use_Sex] as Sex, A.[Use_Password] as [Password], A.Use_Type as UserType, ' +
    'A.[Use_CreateTime] as CreateTime, A.[Use_LastLogin] as LastLoginTime, ' +
    'A.[Use_CityCode] as CityCode, A.[Use_Add] as [Address], ' +
    'A.[Use_Corp] as CompanyName, A.[Use_Tel] as Telephone, ' +
    'A.Use_CityCode as CityCode, A.Use_IsBlock as [Blocked], ' +
    'A.[Use_MobileNo] as MobilePhone, A.[Use_Url] as Website, ' +
    'A.[Use_smsPoint] as SmsPoint, A.[Use_LocPoint] as LocPoint, ' +
    'A.[Use_LocationTime] as AutoLocateTime, A.Use_DiskKeyNo as ComputerID, ' +
    'A.Use_DiskKeyNo2 as ComputerID2, B.UserEmail as AgentTel ' +
    'from [Cxt_56888_net].[dbo].[Users] A left outer join ' +
    '[Cxt_56888_net].[dbo].[Rights_Users] B on B.UserAgentCity like ' +
    '''%%'' + convert(varchar(10), A.Use_CityCode) + ''%%'' where ' +
    'A.Use_UserName = ''%s'' and A.Use_State > 0';
begin
  Result := GetRow(WideFormat(SQLFMT, [userName]), UserInfo, Error);
end;

function TADODatabase.GetUserLocatePoint(UserId: Integer;
  var Quantity: Integer; var Error: TErrorInfo): Boolean;
var
  v: Variant;
begin
  Result := GetSingleField(WideFormat(
    'SELECT Use_LocPoint FROM [Cxt_56888_net].[dbo].[Users] ' +
    'where [Use_ID] = %d', [UserId]), '', v, error);
  if Result then Quantity := v;
end;

function TADODatabase.GetUserSmsPoint(UserId: Integer;
  var Quantity: Integer; var Error: TErrorInfo): Boolean;
var
  v: Variant;
begin
  Result := GetSingleField(WideFormat(
    'SELECT Use_SmsPoint FROM [Cxt_56888_net].[dbo].[Users] ' +
    'where [Use_ID] = %d', [UserId]), '', v, Error);
  if Result then Quantity := v;
end;

function TADODatabase.IsComputerLocked(const ComputerID: AnsiString;
  var Reason: WideString; var Error: TErrorInfo): Boolean;
var
  v: Variant;
begin
  Result := Self.GetSingleField(WideFormat('select Reason from ' +
    'Cxt_56888_net.dbo.LockedComputers where ComputerID = ''%s''',
    [WideString(ComputerID)]), 'Reason', v, Error);
  if Result then Reason := v;
end;

function TADODatabase.LockComputer(const ComputerID: AnsiString;
  const Reason: WideString; var Error: TErrorInfo): Boolean;
begin
  Result := ExecCommand(WideFormat(
    'exec Cxt_56888_net.dbo.LockComputer ''%s'', ''%s''',
    [WideString(ComputerID), Reason]), Error);
end;

function TADODatabase.LockUserByID(UserID: Integer;
  const ComputerID: AnsiString; const Reason: WideString;
  var Error: TErrorInfo): Boolean;
begin
  if ComputerID = '' then
    Result := ExecCommand(WideFormat('update [Cxt_56888_net].[dbo].[Users] ' +
      'set Use_IsBlock = 1 where Use_ID = %d', [UserID]), Error)
  else begin
    Result := Self.LockComputer(ComputerID, Reason, Error);
  end;
end;

function TADODatabase.ModifyAccount(UserInfo: TUserInfo;
  var Error: TErrorInfo): Boolean;
var
  access: TADOAccess;
begin
  access := GetDBConnPool.GetConnection;
  if not Assigned(access) then
  begin
    Result := SystemBusy(Error);
    Exit;
  end;
  with access, access.StoredProc, access.StoredProc.Parameters do
  try
    ProcedureName := '[Cxt_56888_net].[dbo].[Users_ModifyUser]';
    Clear;
    CreateParameter('Use_UserID', ftInteger, pdInput, 4, UserInfo.UserID);
    CreateParameter('Use_Type', ftInteger, pdInput, 4, UserInfo.UserType);
    CreateParameter('Use_RealName', ftString, pdInput, 20, UserInfo.RealName);
    CreateParameter('Use_Sex', ftInteger, pdInput, 4, UserInfo.Sex);
    CreateParameter('Use_IDCardNo', ftString, pdInput, 18, UserInfo.IDCardNo);
    CreateParameter('Use_CityCode', ftInteger, pdInput, 4, UserInfo.CityCode);
    CreateParameter('Use_Tel', ftString, pdInput, 20, UserInfo.Telephone);
    CreateParameter('Use_Add', ftString, pdInput, 500, UserInfo.Address);
    CreateParameter('Use_Corp', ftString, pdInput, 500, UserInfo.CompanyName);
    CreateParameter('Use_MobileNo', ftString, pdInput, 20, UserInfo.MobilePhone);
    CreateParameter('Use_Url', ftString, pdInput, 100, UserInfo.Website);
    Result := ExecStoredProc(Error, True);
  finally
    GetDBConnPool.ReleaseConnection(access);
  end;
end;

function TADODatabase.ModifyLocPerson(List: TDzPersistentList;
  out Modified: Integer; var Error: TErrorInfo): Boolean;
var
  access: TADOAccess;
  i: Integer;
  person: TLocPerson;
begin
  access := GetDBConnPool.GetConnection;
  if access = nil then
  begin
    Result := SystemBusy(Error);
    Exit;
  end;
  Modified := 0;
  with access, StoredProc.Parameters do
  try
    StoredProc.ProcedureName := '[Cxt_56888_net].[dbo].[CarInfo_UpdatePeopleInfo]';
    Clear;
    CreateParameter('SuiCheShouJi',ftString, pdInput, 50, null);
    CreateParameter('SiJiXingMing', ftString, pdInput, 50, null);
    CreateParameter('Sex', ftString, pdInput, 2, null);
    CreateParameter('BeiZhu', ftString, pdInput, 1000, null);
    CreateParameter('CheLiangBianHao', ftInteger, pdInput, 4, null);
    CreateParameter('SuoShuYongHu', ftInteger, pdInput, 4, null);
    CreateParameter('ReturnCode', ftInteger, pdOutput, 4, null);
    for i := 0 to List.Count - 1 do
    begin
      person := TLocPerson(List[i]);
      Items[0].Value := person.Phone;
      Items[1].Value := person.Name;
      Items[2].Value := person.Sex;
      Items[3].Value := person.Remark;
      Items[4].Value := person.GUID;
      Items[5].Value := person.UserID;
      Result := ExecStoredProc(Error, True);
      if Result then Inc(Modified)
      else Break;
    end;
  finally
    GetDBConnPool.ReleaseConnection(access);
  end;
  Result := Modified > 0;
  if Result then 
  begin
    Error.Code := CXT_E_SUCCESS;
    Error.Desc := '';
    Result := True;
  end;
end;

function TADODatabase.ModifyLBMPState(const Phone: AnsiString;
  State: Integer; var Error: TErrorInfo): Boolean;
begin
  Result := ExecCommand(WideFormat(
    'update [Cxt_56888_net].[dbo].[CarInfo] set [ZhuCeFou] = ' +
    '%d where [SuiCheShouJi] = %s', [State, WideString(Phone)]), Error);
end;

function TADODatabase.ModifyLocTrace(Tracing: TVehicleTracing;
  var Error: TErrorInfo): Boolean;
begin
  Result := UpdateLocTrace(Tracing, Error);
end;

function TADODatabase.ModifyPassword(UserID: Integer;
  const OldPassword, NewPassword: AnsiString;
  var Error: TErrorInfo): Boolean;
var
  access: TADOAccess;
  retid: Integer;
begin
  access := GetDBConnPool.GetConnection;
  if access = nil then
  begin
    Result := SystemBusy(Error);
    Exit;
  end;
  with access, access.StoredProc, access.StoredProc.Parameters do
  try
    ProcedureName := '[Cxt_56888_net].[dbo].[Users_EditPassword]';
    Clear;
    CreateParameter('Use_ID', ftInteger, pdInput, 4, UserID);
    CreateParameter('Use_Password', ftString, pdInput, 50, NewPassword);
    CreateParameter('OldPassword', ftString, pdInput, 50, OldPassword);
    CreateParameter('ReturnCode', ftInteger, pdOutput, 4, null);
    Result := ExecStoredProc(Error, True);
    if Result then
    begin
      retid := ParamValues['ReturnCode'];
      case retid of
        0: ;
        1:
          begin
            Error.Code := CXT_E_NO_DATA;
            Result := False;
          end;
        else begin
          Error.Code := CXT_E_AUTHENTICATION;
          Result := False;
        end;
      end;
    end
  finally
    GetDBConnPool.ReleaseConnection(access);
  end;
end;

function TADODatabase.ModifyPriVehicle(vehicle: TVehicle;
  var Error: TErrorInfo): Boolean;
begin
  Result := AddOrModifyPriVehicle(opModify, vehicle, Error);
end;

function TADODatabase.RemoveLocPerson(List: TDzPersistentList;
  var Removed: Integer; var Error: TErrorInfo): Boolean;
begin
  Result := RemovePriVehicle(List, Removed, Error);
end;

function TADODatabase.RemoveLocTrace(ID: Integer;
  var Error: TErrorInfo): Boolean;
begin
  Result := ExecCommand(WideFormat('delete from [Cxt_56888_net].[dbo].' +
    '[CarInfo_AutoLoc] where AutoLocID = %d', [ID]), Error);
end;

function TADODatabase.SaveLocateResult(const Phone, Longitude, Latitude: AnsiString;
  Address, CityName: WideString; CityID, UserID, ObjectID, Consume: Integer;
  Method: TLbmpLocType; var Error: TErrorInfo): Boolean;
begin
  Result := ExecCommand(WideFormat(
    'exec Cxt_56888_net.dbo.Car_UpdateLocation2 %d, 0, %d, %d, %d, %d, ' +
    '''%s'', 0, %d, ''%s'', ''%s'', ''%s'', ''%s'', 3'#13#10,
    [Ord(not AppConfig.UseNewTrackServer), Consume, Ord(Method) + 1, UserID,
    ObjectID, WideString(Phone), CityID, CityName,
    Address, WideString(Longitude), WideString(Latitude)]), Error);
end;

function TADODatabase.SaveLogin(UserID: Integer; LoginTime: TDateTime;
  const Source, ComputerID: AnsiString; var Error: TErrorInfo): Boolean;
begin
  Result := ExecCommand(WideFormat('exec [Cxt_56888_net].[dbo].[SaveLogin] ' +
    '%d, ''%s'', ''%s'', ''%s''',  [UserID, WideString(ComputerID),
     WideString(Source), FormatDateTime('yyyy-m-d hh:nn:ss', LoginTime)]), Error);
end;

function TADODatabase.SaveSms(const Sender, Recver: WideString;
  const Content: WideString; SendTime: TDateTime;
  var Error: TErrorInfo): Boolean;
begin
  Result := ExecCommand(WideFormat('insert into [Cxt_56888_net].[dbo].[smsHistoryRec] ' +
    '([sms_Contents], [sms_AccNumber], [sms_UserName] ,[sms_AddTime]) values ' +
    '(''%s'', ''%s'', ''%s'', ''%s'')', [Content, Recver, Sender,
      FormatDateTime('yyyy-m-d hh:nn:ss', SendTime)]), Error);
end;

function TADODatabase.SetAutoLocTime(userID, hour: Integer;
  var Error: TErrorInfo): Boolean;
begin
  Result := ExecCommand(WideFormat(
    'update [Cxt_56888_net].[dbo].Users set Use_LocationTime = %d ' +
    'where Use_ID = %d; update [Cxt_56888_net].[dbo].CarInfo set ' +
    'AutoLocTime = %d where SuoShuYongHu = %d',
    [hour, userID, hour, userID]), Error);
end;

function TADODatabase.UnlockCompter(const ComputerID: AnsiString;
  var Error: TErrorInfo): Boolean;
begin
  Result := ExecCommand(WideFormat(
    'delete from [Cxt_56888_net].[dbo].LockedComputers ' +
    'where ComputerID = ''%s''', [WideString(ComputerID)]), Error);
end;

function TADODatabase.ModifyComputerID(UserID: Integer;
  const ComputerID: AnsiString; var Error: TErrorInfo): Boolean;
begin
  Result := Self.ExecCommand(WideFormat('update Cxt_56888_net.dbo.Users ' +
    'set Use_DiskKeyNo = ''%s'' where Use_ID = %d',
    [WideString(ComputerID), UserID]), Error);
end;

function TADODatabase.UpdateLocTrace(Tracing: TVehicleTracing;
  var Error: TErrorInfo): Boolean;
var
  access: TADOAccess;
begin
  access := GetDBConnPool.GetConnection;
  if access = nil then
  begin
    Result := SystemBusy(Error);
    Exit;
  end;
  try
    with access.StoredProc, access.StoredProc.Parameters do 
    begin
      Clear;
      ProcedureName := '[Cxt_56888_net].[dbo].[CarInfo_AutoLoc_AddUpdate]';
      CreateParameter('AutoLocID', ftInteger, pdInput, 4, Tracing.AutoLocID);
      CreateParameter('CarID', ftInteger, pdInput, 4, Tracing.CarID);
      CreateParameter('UserID', ftInteger, pdInput, 4, Tracing.UserID);
      CreateParameter('CarMobile', ftWideString, pdInput, 32, Tracing.CarMobile);
      CreateParameter('InMobile', ftWideString, pdInput, 128, Tracing.InMobile);
      CreateParameter('ToMobile', ftWideString, pdInput, 128, Tracing.ToMobile);
      CreateParameter('TimeSlot', ftWideString, pdInput, 72, Tracing.TimeSlot);
      CreateParameter('StartTime', ftDateTime, pdInput, 8, Tracing.StartTime);
      CreateParameter('StopTime', ftDateTime, pdInput, 8, Tracing.StopTime);
      CreateParameter('SmsContent', ftWideString, pdInput,
        256, tracing.SmsContent);
      CreateParameter('AutoLocIsOpen', ftInteger, pdInput, 4, 1);
      CreateParameter('ReturnCode', ftInteger, pdOutput, 4, 0);
      Result := access.ExecStoredProc(Error, True);
    end;  
  finally
    GetDBConnPool.ReleaseConnection(access);
  end;
end;

function TADODatabase.DecUserLocatePoint(UserID, Quantity: Integer;
  var Error: TErrorInfo): Boolean;
begin
  Result := ExecCommand(WideFormat(
    'update Cxt_56888_net.dbo.Users set Use_LocPoint = ' +
    'Use_LocPoint - %d where Use_ID = %d', [Quantity, UserID]), Error);
end;

function TADODatabase.DecUserSmsPoint(UserId, Quantity: Integer;
  var Error: TErrorInfo): Boolean;
begin
  Result := ExecCommand(WideFormat(
    'update [Cxt_56888_net].[dbo].[Users] set Use_SmsPoint = ' +
    'Use_SmsPoint - %d where [Use_ID] = %d', [Quantity, UserId]), Error);
end;

function TADODatabase.RemovePriVehicle(List: TDzPersistentList;
  var Removed: Integer; var Error: TErrorInfo): Boolean;
const
  SQLCMD = 'update [Cxt_56888_net].[dbo].[CarInfo] set Car_Del = 1 ' +
    'where Car_Del = 0 and ((1 = 0) ';
var
  i, num: Integer;
  def: TDeleteObjectDef;
  access: TADOAccess;
  function RemoveBatch: Boolean;
  begin
    with access.Query do
    begin
      SQL.Add(')');
      Result := access.ExecSQL('', Error, True, @num);
      if Result then
      begin
        Inc(Removed, num);
        SQL.Clear;
        SQL.Add(SQLCMD);
      end;
    end;
  end;
begin
  access := GetDBConnPool.GetConnection;
  if access = nil then
  begin
    Result := SystemBusy(Error);
    Exit;
  end;
  removed := 0;
  Result := True;
  with access.Query do
  try
    SQL.Clear;
    SQL.Add(SQLCMD);
    for i := 0 to List.Count - 1 do
    begin
      def := TDeleteObjectDef(List[i]);
      if (i mod 10 = 0) and (i <> 0) then
      begin
        Result := RemoveBatch;
        if not Result then Break;
      end;
      SQL.Add(WideFormat('OR (CheLiangBianHao = %d AND SuoShuYongHu = %d) ',
        [def.ObjectID, def.UserID]));
    end;
    if Result and (SQL.Count > 1) then Result := RemoveBatch;
  finally
    GetDBConnPool.ReleaseConnection(access);
  end;
  if Removed > 0 then
  begin
    Error.Code := CXT_E_SUCCESS;
    Error.Desc := '';
    Result := True;
  end;
end;

end.

